<template>
  <div class="game-container">
    <div class="instructions">使用方向键和A、D、S、W、Q键移动和旋转方块。按空格键和E键立即下落。</div>
    <div class="info-panel">
      <div>
        总分数: <span id="total-score">{{ totalScore }}</span><br>
        下一个方块:<br>
        <canvas id="next-block-canvas" width="60" height="60"></canvas><br>
        状态: <span id="status">{{ isGameOver ? '游戏结束' : '游戏中' }}</span>
      </div>
    </div>
    <div class="player-container">
      <div class="player-area">
        <canvas id="tetris-canvas" width="800" height="533"></canvas>
        <div id="overlay" class="overlay" :style="{ display: isGameOver ? 'block' : 'none' }">
          <div class="overlay-content">
            <h2>游戏结束</h2>
            <p>您的最终分数: <span id="final-score">{{ totalScore }}</span></p>
            <button @click="restartGame">重新开始游戏</button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      scale: 26.67, // 缩小比例
      arenaWidth: 30,
      arenaHeight: 20,
      colors: [
        null,
        '#FF0D72',
        '#0DC2FF',
        '#0DFF72',
        '#F538FF',
        '#FF8E0D',
        '#FFE138',
        '#3877FF'
      ],
      arena: this.createMatrix(this.arenaWidth, this.arenaHeight),
      player1: {
        pos: { x: 0, y: 0 },
        matrix: null,
        score: 0,
        dropCounter: 0,
        dropInterval: 500, // 减少时间间隔以加快下降速度
        lastTime: 0,
        isGameOver: false,
      },
      player2: {
        pos: { x: 15, y: 0 }, // 玩家2从中间开始
        matrix: null,
        score: 0,
        dropCounter: 0,
        dropInterval: 500, // 减少时间间隔以加快下降速度
        lastTime: 0,
        isGameOver: false,
      },
      isGameOver: false,
      totalScore: 0,
    };
  },
  mounted() {
    this.arena = this.createMatrix(this.arenaWidth, this.arenaHeight);
    this.playerReset(1);
    this.playerReset(2);
    this.updateScore();
    this.update(); // 确保 update 方法被调用
    window.addEventListener('keydown', this.handleKeyDown);
  },
  beforeDestroy() {
    window.removeEventListener('keydown', this.handleKeyDown);
  },
  methods: {
    createMatrix(w, h) {
      const matrix = [];
      while (h--) {
        matrix.push(new Array(w).fill(0));
      }
      return matrix;
    },
    drawMatrix(matrix, offset, context) {
      matrix.forEach((row, y) => {
        row.forEach((value, x) => {
          if (value !== 0) {
            context.fillStyle = this.colors[value];
            context.strokeStyle = 'black';
            context.lineWidth = 0.5;
            context.fillRect((x + offset.x) * this.scale, (y + offset.y) * this.scale, this.scale, this.scale);
            context.strokeRect((x + offset.x) * this.scale, (y + offset.y) * this.scale, this.scale, this.scale);
          }
          // 添加网格线
          context.strokeStyle = 'gray';
          context.strokeRect((x + offset.x) * this.scale, (y + offset.y) * this.scale, this.scale, this.scale);
        });
      });
    },
    merge(arena, player) {
      player.matrix.forEach((row, y) => {
        row.forEach((value, x) => {
          if (value !== 0) {
            arena[y + player.pos.y][x + player.pos.x] = value;
          }
        });
      });
    },
    collide(arena, player) {
      const [m, o] = [player.matrix, player.pos];
      for (let y = 0; y < m.length; ++y) {
        for (let x = 0; x < m[y].length; ++x) {
          if (m[y][x] !== 0 &&
             (arena[y + o.y] &&
              arena[y + o.y][x + o.x]) !== 0) {
            return true;
          }
        }
      }
      return false;
    },
    createPiece(type) {
      switch (type) {
        case 'T':
          return [
            [0, 1, 0],
            [1, 1, 1],
            [0, 0, 0]
          ];
        case 'O':
          return [
            [2, 2],
            [2, 2]
          ];
        case 'L':
          return [
            [0, 0, 3],
            [3, 3, 3],
            [0, 0, 0]
          ];
        case 'J':
          return [
            [4, 0, 0],
            [4, 4, 4],
            [0, 0, 0]
          ];
        case 'I':
          return [
            [0, 5, 0, 0],
            [0, 5, 0, 0],
            [0, 5, 0, 0],
            [0, 5, 0, 0]
          ];
        case 'S':
          return [
            [0, 6, 6],
            [6, 6, 0],
            [0, 0, 0]
          ];
        case 'Z':
          return [
            [7, 7, 0],
            [0, 7, 7],
            [0, 0, 0]
          ];
        default:
          throw new Error("未知的方块类型");
      }
    },
    rotate(matrix, dir) {
      for (let y = 0; y < matrix.length; ++y) {
        for (let x = 0; x < y; ++x) {
          [
            matrix[x][y],
            matrix[y][x],
          ] = [
            matrix[y][x],
            matrix[x][y],
          ];
        }
      }

      if (dir > 0) {
        matrix.forEach(row => row.reverse());
      } else {
        matrix.reverse();
      }
    },
    update(time = 0) {
      if (this.isGameOver) return;

      const deltaTime = time - this.lastTime;
      this.lastTime = time;

      this.player1.dropCounter += deltaTime;
      this.player2.dropCounter += deltaTime;

      if (this.player1.dropCounter > this.player1.dropInterval) {
        this.playerDrop(1);
      }

      if (this.player2.dropCounter > this.player2.dropInterval) {
        this.playerDrop(2);
      }

      this.draw();
      requestAnimationFrame(this.update);
    },
    playerDrop(playerNum) {
      const player = playerNum === 1 ? this.player1 : this.player2;
      player.pos.y++;
      if (this.collide(this.arena, player)) {
        player.pos.y--;
        // 检查两个玩家的方块是否重合
        if (this.checkOverlap()) {
          player.pos.y++;
          return;
        }
        this.merge(this.arena, player);
        this.playerReset(playerNum);
        this.arenaSweep();
        this.updateScore();
      }
      player.dropCounter = 0;
    },
    checkOverlap() {
      const player1 = this.player1;
      const player2 = this.player2;

      for (let y = 0; y < player1.matrix.length; ++y) {
        for (let x = 0; x < player1.matrix[y].length; ++x) {
          if (player1.matrix[y][x] !== 0 && player2.matrix[y + player2.pos.y - player1.pos.y] &&
              player2.matrix[y + player2.pos.y - player1.pos.y][x + player2.pos.x - player1.pos.x] !== 0) {
            return true;
          }
        }
      }

      for (let y = 0; y < player2.matrix.length; ++y) {
        for (let x = 0; x < player2.matrix[y].length; ++x) {
          if (player2.matrix[y][x] !== 0 && player1.matrix[y + player1.pos.y - player2.pos.y] &&
              player1.matrix[y + player1.pos.y - player2.pos.y][x + player1.pos.x - player2.pos.x] !== 0) {
            return true;
          }
        }
      }

      return false;
    },
    playerMove(playerNum, dir) {
      const player = playerNum === 1 ? this.player1 : this.player2;
      player.pos.x += dir;
      if (this.collide(this.arena, player)) {
        player.pos.x -= dir;
      }
    },
    playerRotate(playerNum, dir) {
      const player = playerNum === 1 ? this.player1 : this.player2;
      const pos = player.pos.x;
      let offset = 1;
      this.rotate(player.matrix, dir);
      while (this.collide(this.arena, player)) {
        player.pos.x += offset;
        offset = -(offset + (offset > 0 ? 1 : -1));
        if (offset > player.matrix[0].length) {
          this.rotate(player.matrix, -dir);
          player.pos.x = pos;
          return;
        }
      }
    },
    playerReset(playerNum) {
      const player = playerNum === 1 ? this.player1 : this.player2;
      const pieces = 'ILJOTSZ';
      player.matrix = this.createPiece(pieces[pieces.length * Math.random() | 0]);
      player.pos.y = 0;
      player.pos.x = playerNum === 1 ? 0 : 15; // 玩家1从左边开始，玩家2从中间开始
      if (this.collide(this.arena, player)) {
        this.gameOver();
      }
      this.drawNextBlock(player.matrix);
    },
    arenaSweep() {
      let rowCount = 1;
      outer: for (let y = this.arena.length - 1; y > 0; --y) {
        for (let x = 0; x < this.arena[y].length; ++x) {
          if (this.arena[y][x] === 0) {
            continue outer;
          }
        }
        const row = this.arena.splice(y, 1)[0].fill(0);
        this.arena.unshift(row);
        ++y;

        this.totalScore += rowCount * 10;
        rowCount *= 2;
      }
    },
    updateScore() {
      document.getElementById('total-score').innerText = this.totalScore;
      document.getElementById('final-score').innerText = this.totalScore;
    },
    draw() {
      const canvas = document.getElementById('tetris-canvas');
      const context = canvas.getContext('2d');
      if (!context) {
        console.error('Canvas context is not available');
        return;
      }
      context.fillStyle = '#000';
      context.fillRect(0, 0, canvas.width, canvas.height);

      this.drawMatrix(this.arena, { x: 0, y: 0 }, context);
      this.drawMatrix(this.player1.matrix, this.player1.pos, context);
      this.drawMatrix(this.player2.matrix, this.player2.pos, context);
    },
    drawNextBlock(matrix) {
      const nextBlockCanvas = document.getElementById('next-block-canvas');
      const nextBlockContext = nextBlockCanvas.getContext('2d');
      nextBlockContext.clearRect(0, 0, nextBlockCanvas.width, nextBlockCanvas.height);
      nextBlockContext.fillStyle = '#000';
      nextBlockContext.fillRect(0, 0, nextBlockCanvas.width, nextBlockCanvas.height);

      this.drawMatrix(matrix, { x: 0, y: 0 }, nextBlockContext);
    },
    handleKeyDown(event) {
      if (this.isGameOver) return;

      if (event.keyCode === 37 || event.key === 'ArrowLeft') { // 左箭头键
        this.playerMove(1, -1);
      } else if (event.keyCode === 39 || event.key === 'ArrowRight') { // 右箭头键
        this.playerMove(1, 1);
      } else if (event.keyCode === 40 || event.key === 'ArrowDown') { // 下箭头键
        this.playerDrop(1);
      } else if (event.keyCode === 38 || event.key === 'ArrowUp') { // 上箭头键
        this.playerRotate(1, 1);  // 顺时针旋转
      } else if (event.keyCode === 32 || event.key === ' ') { // 空格键
        while (!this.collide(this.arena, this.player1)) {
          this.player1.pos.y++;
        }
        this.player1.pos.y--;
        this.merge(this.arena, this.player1);
        this.playerReset(1);
        this.arenaSweep();
        this.updateScore();
      } else if (event.keyCode === 65) { // A键
        this.playerMove(2, -1);
      } else if (event.keyCode === 68) { // D键
        this.playerMove(2, 1);
      } else if (event.keyCode === 83) { // S键
        this.playerDrop(2);
      } else if (event.keyCode === 87) { // W键
        this.playerRotate(2, 1);  // 顺时针旋转
      } else if (event.keyCode === 69) { // E键
        while (!this.collide(this.arena, this.player2)) {
          this.player2.pos.y++;
        }
        this.player2.pos.y--;
        this.merge(this.arena, this.player2);
        this.playerReset(2);
        this.arenaSweep();
        this.updateScore();
      }
    },
    gameOver() {
      this.isGameOver = true;
    },
    restartGame() {
      this.arena = this.createMatrix(this.arenaWidth, this.arenaHeight);
      this.player1.pos = { x: 0, y: 0 };
      this.player2.pos = { x: 15, y: 0 };
      this.player1.matrix = null;
      this.player2.matrix = null;
      this.player1.score = 0;
      this.player2.score = 0;
      this.totalScore = 0;
      this.player1.dropCounter = 0;
      this.player2.dropCounter = 0;
      this.player1.dropInterval = 1000;
      this.player2.dropInterval = 1000;
      this.player1.lastTime = 0;
      this.player2.lastTime = 0;
      this.player1.isGameOver = false;
      this.player2.isGameOver = false;
      this.isGameOver = false;
      this.playerReset(1);
      this.playerReset(2);
      this.updateScore();
      this.update();
    },
  },
};
</script>

<style scoped>
body {
  background-color: #222;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 0;
  position: relative;
  font-family: Arial, sans-serif;
}
.game-container {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.player-container {
  display: flex;
  justify-content: center;
  width: 820px; /* Adjusted width to fit both players side by side */
}
.player-area {
  position: relative;
  width: 800px; /* Set a fixed width for the combined player area */
}
canvas {
  border: 1px solid #000;
  background-color: #000;
}
.info-panel {
  color: #fff;
  font-size: 1em;
  text-align: center;
  margin-bottom: 10px;
  padding: 10px;
  background-color: rgba(0, 0, 0, 0.7);
  border-radius: 5px;
  width: 800px; /* Adjusted width to fit both players side by side */
  display: flex;
  justify-content: center;
}
.instructions {
  position: absolute;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  color: #fff;
  font-size: 1.2em;
}
.overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.7);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}
.overlay-content {
  background-color: #fff;
  padding: 20px;
  border-radius: 10px;
  text-align: center;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}
.overlay button {
  margin-top: 10px;
  padding: 10px 20px;
  font-size: 1em;
  cursor: pointer;
  border: none;
  border-radius: 5px;
  background-color: #0DC2FF;
  color: #fff;
}
.overlay button:hover {
  background-color: #0B9DD9;
}
</style>